from itertools import chain as ichain
from myelin.server.core.ft import ModelDriver
from myelin.Ns import MYELIN, DC

from nodetypes import config
from nodetypes.lib import Utils

from Ft.Rdf.Drivers.Operators import OPERATORS, IdentityFilter

import Sorters

SORT_ASCENDING = False
SORT_DESCENDING = True

class SortByEnums:
    
    REVELANCE_SCORE     = 0    
    TITLE_SORT          = 1
    MODIFIED_DATE       = 2
    CREATED_DATE        = 3
    MODIFIER_NICK       = 4
    CREATOR_NICK        = 5
    

class Service(object):
    
    sort_by = (
        Sorters.RevelanceSorter,        
        Sorters.TitleSorter,
        Sorters.ModifiedDateSorter,
        Sorters.CreatedDateSorter,
        Sorters.ModifierNickSorter,
        Sorters.CreatorNickSorter,
    )
    
    sort_order = (
        SORT_ASCENDING,
        SORT_DESCENDING,
    ) 
    
    defaults = config.METASEARCH_PARAMS  
    
    #newBaseModel = Document.Retrieve
    #newBaseModelDriver = staticmethod(Document.Initialize)
    
    newDbDriver = staticmethod(ModelDriver.FromRepo)
    
    def fetchParams(self, context, source, params, errors):
        return params, errors
    
    def execute(self, context, source):
        
        params, errors = self.fetchParams(context, source, {}, {})
        if errors or not params['textindex-uri']:
            eventData = context.event.data        
            eventData.params = params
            eventData.errors = errors
            return False
        
        keywords = params['query'].lower()
        
        locale = params['language'] or None
        #if locale:
            #if params['region']:
            #    locale = Utils.JoinLocale(locale, params['region'])
        #else:
        #    locale = None
        
        # FIXME: need to see if scope is mappable to a public uri as well
        #uriMapper = context.uriMapper.apply
        count = params['count']
        start = params['page']*count
        range = (start, count)
        
        indices = map(context.repo.fetchResourceByUri,params['textindex-uri'])        
        if len(indices) > 1:
            results = list(indices[0].mergeSearch(
                indices[1:],
                keywords,
                locale,
                range = range,
                matchFilter = lambda d,f=context.acls.checkNodeAcls: f('ftss://' + d[0])
            ))
        else:
            results = list(indices[0].search(
                keywords,
                locale,
                range = range,
                matchFilter = lambda d,f=context.acls.checkNodeAcls: f('ftss://' + d[0])
            ))
        
        #if results:
        #    #print "Results:"
        #    #print results
        #    total = len(results)
        #    results = results[start:start + count]
        #    searchPos = (start+1, start + len(results))
        #else:
        #    searchPos = (0,0)
        #    total = 0
            
        print "RESULTS: "
        print results
        
        eventData = context.event.data
        
        eventData.params = params
        eventData.errors = errors
        eventData.results = results[1:]
        eventData.resultsHeader = results[0]
        eventData.searchLocale = locale
        eventData.searchBaseIndex = start
        #eventData.searchPos = searchPos
        #eventData.searchTotal = total        
        
        return True
    
    #def execute(self, context, source):
    #    
    #    params, errors = self.fetchParams(context, source, {}, {})
    #    if errors or not params['textindex-uri']:
    #        eventData = context.event.data        
    #        eventData.params = params
    #        eventData.errors = errors
    #        return False
        
        #dbDriver = self.newBaseModelDriver(
        #    self.newDbDriver(
        #        context.repo,
        #        reduce(
        #            lambda a,b:a+b,
        #            params['default-graph-uri'].values(),
        #            []
        #        )
        #    ),
        #    uriScopeResolver = context.uriScopeResolver
        #)        
        
        #keywords = params['keywords'].lower()
        #filters = [
        #    IdentityFilter().predicate(
        #        DC + u'(title|description|subject)',                
        #        OPERATORS.R
        #    ).object(                
        #        keywords,
        #        OPERATORS.RI
        #    ),
        #    IdentityFilter().predicate(
        #        MYELIN + u'tag'
        #    ),
        #]
        
        #locale = params['language']
        #if locale:
            #if params['region']:
                #locale = Utils.JoinLocale(locale, params['region'])
                #filters.append(
                #    IdentityFilter().predicate(
                #        DC+'language'
                #    ).object(
                #        locale
                #    )
                #)
            #else:
            #    filters.append(
            #        IdentityFilter().predicate(
            #            DC+'language'
            #        ).object(
            #            locale+'-',                        
            #            OPERATORS.RI
            #        )
            #    )  
        #elif params['region']:
            #locale = params['region']
            #filters.append(
            #    IdentityFilter().predicate(
            #        DC+'language'
            #    ).object(                    
            #        '-'+locale,
            #        OPERATORS.RI
            #    )
            #) 
            
        # check for effective date
        #if params['efdFlag']:
        #    #print "EFFECTIVE DATE: %s" % _effDate
        #    filters.append(
        #        IdentityFilter().predicate(
        #            MYELIN+'effectiveDate'
        #        ).object(
        #            "%04d-%02d-01T00:00:00Z" % (
        #                params['efdYr'],
        #                params['efdMon']
        #            ),                    
        #            OPERATORS.GTE
        #        )
        #    )
            
        #if __debug__:
        #    print "SEARCH:"
        #    print " keywords: %s" % keywords
        #    print " locale: %s" % locale
        #    print " effDate: %s" % effDate        
        
        # FIXME: need to see if scope is mappable to a public uri as well
        #uriMapper = context.uriMapper.apply    
        #Model = self.newBaseModel
        #results = sorted(
        #    iter(
        #        Model(dbDriver, n[0],n[1],n[1])
        #        for n in dbDriver.findScopedResources(
        #            filters,
        #            scopeFilter = context.acls.checkNodeAcls #lambda n: uriMapper(n) and acls(n)
        #        )
        #    ),
        #    self.sort_by[params['sort-by']](keywords),
        #    reverse=params['sort-direction'] and True or False
        #)
        
        #if results:
            #print "Results:"
            #print results
            #total = len(results)
            #count = params['count']
            #start = params['page'] * count
            #results = results[start:start + count]
            #searchPos = (start+1, start + len(results))
        #else:
        #    searchPos = (0,0)
        #    total = 0
        
        #eventData = context.event.data
        #
        #eventData.params = params
        #eventData.errors = errors
        #eventData.results = results
        #eventData.searchLocale = locale
        #eventData.searchPos = searchPos
        #eventData.searchTotal = total        
        #
        #return True
    
    
# cleanup
del config